﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using A2DFramework.QueueService.Providers;
using A2DFramework.AssemblyService;
using A2DFramework.InstanceService;

namespace A2DFramework.QueueService
{
    public class QueueService : IQueue
    {
        private IQueueProvider srvProvider=ObjectFactory.Resolve<IQueueProvider>();


        /// <summary>
        /// 检查相应的队列是否存在，如不存在则自动建立
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void CreateIfNotExists<T>()
        {
            string queueName = QueueHelper.GetQueueName<T>();
            string responseQueueName = QueueHelper.GetResponseQueueName<T>();

            if (!srvProvider.IsQueueExists(queueName))
                srvProvider.CreateQueue(queueName);

            if (!srvProvider.IsQueueExists(responseQueueName))
                srvProvider.CreateQueue(responseQueueName);
        }

        public void SendRequest2Worker<T>(Message<T> msg)
        {
            QueuePrepare<T>();

            string queueName = QueueHelper.GetQueueName<T>();

            InnerMessageWrapper msmqCmd = new InnerMessageWrapper();
            msmqCmd.Inject(msg.Body);

            srvProvider.SendMessage(queueName, msmqCmd);
            msg.ID = msmqCmd.MessageID;
        }

        public void SendRequest2Worker<T>(T msg)
        {
            QueuePrepare<T>();

            Message<T> newMsg = new Message<T>();
            newMsg.Body = msg;
            SendRequest2Worker<T>(newMsg);
        }

        public Message<T> GetRequestFromClient<T>()
        {
            QueuePrepare<T>();

            string queueName = QueueHelper.GetQueueName<T>();

            InnerMessageWrapper msmqCmd = srvProvider.ReceiveMessage(queueName);
            Message<T> msg = new Message<T>() 
            {
                ID=msmqCmd.MessageID, Body = msmqCmd.Extract<T>() 
            };

            return msg;
        }

        public void SendResponse2Client<T>(T msg, string requestMsgId) 
        {
            QueuePrepare<T>();

            string queueName = QueueHelper.GetResponseQueueName<T>();

            InnerMessageWrapper msmqCmd = new InnerMessageWrapper();
            msmqCmd.CorrelationID = requestMsgId;
            msmqCmd.Inject(msg);

            srvProvider.SendMessage(queueName, msmqCmd);
        }

        public T GetResponseFromWorker<T>(string requestMsgId) 
        {
            QueuePrepare<T>();

            string queueName = QueueHelper.GetResponseQueueName<T>();

            InnerMessageWrapper msmqCmd = srvProvider.ReceiveMessage(queueName, requestMsgId);

            return msmqCmd.Extract<T>();
        }


        private static Dictionary<Type, bool> queueExistsMapping = new Dictionary<Type, bool>();
        private static object objLock_queueExistsMapping = new object();

        private void QueuePrepare<T>()
        {
            lock (objLock_queueExistsMapping)
            {
                if (!queueExistsMapping.ContainsKey(typeof(T)))
                    queueExistsMapping.Add(typeof(T), false);
                else if (queueExistsMapping[typeof(T)])
                    return;

                CreateIfNotExists<T>();

                queueExistsMapping[typeof(T)] = true;
            }
        }
    }
}
